/************************************************
 * Author       :   XXY
 * Blog         :   https://www.cnblogs.com/jzyl
 * Gitee        :   https://gitee.com/xiaobaichong
 * Email        :   1047185209@QQ.com
 * FileName     :   FSM_Animator.cs
 * CreateData   :   2023/5/31 22:38:02
 * UnityVersion :   2021.3.20f1c1
 * Description  :   使用Unity Animator 动画状态机实现有限状态机
************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;

namespace Main
{
    /*
      *    Demo：给予Unity Animator 实现状态机
      *    FSM_Animator fsm = new FSM_Animator(m_animator);
      *    fsm["起床"] = new FSM_Action(() =>
      *    {
      *    Debug.Log("准备起床");
      *    }, () =>
      *    {
      *    Debug.Log("真在起床");
      *    }, () =>
      *    {
      *    Debug.Log("结束起床");
      *    });
      *    fsm["出门"] = new FSM_Action(() =>
      *    {
      *    Debug.Log("准备出门");
      *    }, () =>
      *    {
      *    Debug.Log("真在出门");
      *    }, () =>
      *    {
      *    Debug.Log("结束出门");
      *    });
     */

    public class FSM_Animator
    {
        private Animator m_animator;
        private Dictionary<int, FSM_Action> m_fsm;// 状态事件集合
        private int m_currentState;             // 当前状态
        private int m_currentId                 // 当前状态id
        {
            get
            {
                return m_currentState;
            }
            set
            {
                if (m_currentState != value)
                {
                    this[m_currentState]?.Exit?.Invoke();
                    this[value]?.Enter?.Invoke();
                    m_currentState = value;
                }
            }
        }
        public FSM_Animator(Animator animator)// 构造函数
        {
            m_fsm = new Dictionary<int, FSM_Action>();
            m_animator = animator;
        }
        public FSM_Action this[string stateName]
        {
            get
            {
                int id = StringToHash(stateName);
                return this[id];
            }
            set
            {
                int id = StringToHash(stateName);
                if (value == null)// 移除
                {
                    m_fsm.Remove(id);   // 有则返回 TRUE ，没有则返回 FALSE
                }
                else
                {
                    m_fsm[id] = value; // 有则修改，没有则添加
                }
            }
        }
        private FSM_Action this[int stateName]
        {
            get
            {
                FSM_Action _Action;
                m_fsm.TryGetValue(stateName, out _Action);
                return _Action;
            }
        }
        /// <summary>
        /// 在Update调用使其实现更新执行
        /// </summary>
        public void Update()
        {
            AnimatorStateInfo info = m_animator.GetCurrentAnimatorStateInfo(0);
            m_currentId = info.fullPathHash;
            this[m_currentId]?.Update?.Invoke();
        }
        private int StringToHash(string stateName)
        {
            // 层级+点+状态
            // 层级+点+子状态+点+状态
            // LayerName+"."+StateName[StateMachine+"."+StateName]
            stateName = m_animator.GetLayerName(0) + "." + stateName;
            return Animator.StringToHash(stateName);
        }
        private bool HasState(int stateID)
        {
            return m_animator.HasState(0, stateID);
        }
        private bool HasState(string stateName)
        {
            int id = StringToHash(stateName);
            return HasState(id);
        }
    }
    /// <summary>
    /// 状态事件
    /// </summary>
    public class FSM_Action
    {
        public Action Enter;// 进入-执行一次
        public Action Update;// 更新-执行多次
        public Action Exit;//退出-- 执行一次
        public FSM_Action(Action _enter, Action _update = null, Action _exit = null)
        {
            Enter = _enter;
            Update = _update;
            Exit = _exit;
        }
    }
}
